/*
 *  FILE: 
 *  	string.c
 *
 *  DESCRIPTION:
 *      Simple case-insensitive string compare, along with 
 *  	an implementation of OpenBSD's strlcpy and strlcat.
 *
 *  FUNCTIONS:
 *      string_cmp() - Simple case-insensitive string compare.
 *  	strlcpy()    - Implementation of OpenBSD's strlcpy.
 *  	strlcat()    - Implementation of OpenBSD's strlcat.
 *
 *
 * Copyright (c) 2004-2006 Karlan Thomas Mitchell<karlanmitchell@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *         This product includes software developed by
           Karlan Thomas Mitchell<karlanmitchell@gmail.com>
 * 4. Neither Karlan Thomas Mitchell nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY KARLAN THOMAS MITCHELL AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "string.h"


/*strtoks separotors, and seperates, returns -1 if there is a problem*/
int str_splitup(char *header, char * name, size_t namelen, char * value, size_t valuelen, char * separators){
	char *colonTok;
	char *tPointer;
	char * clean_value = NULL;/*Value with any spaces*/

	tPointer = (char *)strtok_r(header, separators, &colonTok);
	if(tPointer == NULL)
		return -1;

	strlcpy(name, tPointer, namelen);	
	


	if(colonTok == NULL)
		return -1;
		

	clean_value = colonTok;
	if(clean_value != NULL){
		while(*(clean_value) == ' ' ){
			*(clean_value++);
		}
	}

	if(clean_value == NULL || *(clean_value) == 0)
		return -1;

	strlcpy(value, clean_value, valuelen);	

	return 0;
	}


void string_to_upper(char * string){
	int counter = 0;
	int string_len = strlen(string);

	while(counter < string_len){
		string[counter] = toupper(string[counter]);
		counter++;
		}
	}
void string_to_lower(char * string){
	int counter = 0;
	int string_len = strlen(string);

	while(counter < string_len){
		string[counter] = tolower(string[counter]);
		counter++;
		}
	}

int signed string_cmp(char * s1, char * s2){
	int signed   adjust = 0;
	size_t       count  = 0;
	int unsigned s1_char;
	int unsigned s2_char;

	while(s1[count] != 0 && s2[count] != 0){
		s1_char = tolower(s1[count]);
		s2_char = tolower(s2[count]);
		if(s1_char > s2_char)
			return 1;
		else if(s1_char < s2_char)
			return -1;
		count++;
	}
	return 0;
	
}

void strcreplace(char * string, char what, char with){
    size_t string_len = strlen(string);
    size_t posc;
    if(string_len <= 0)
        return;

    for(posc = 0 ; posc < string_len ; posc++){
        if(string[posc] == what)
            string[posc] = with;
    }
}


void strstrreplace(char * string, size_t string_len, char * what, char * with){
     char * string_old = (char *)malloc((strlen(string) + 1) * sizeof(char));
     strcpy(string_old, string);
     *(string) = 0;

     char * rest = string_old;
     char * cur_pntr;
     char   tmp_char;
     size_t what_len = strlen(what);

     while(1){
	cur_pntr = strstr(rest, what);
	if(cur_pntr == NULL)
	   break;

        tmp_char    = *(cur_pntr);
        *(cur_pntr) = 0;

	strlcat(string, rest, string_len);
	strlcat(string, with, string_len);

        *(cur_pntr) = tmp_char;
        rest = &*(cur_pntr + what_len);
     }
	strlcat(string, rest, string_len);

     free(string_old);
}



/*
decode_range:
	This functions takes in the value of the HTTP range header
	skips the 'bytes=' and
*/
int decode_range(char * client_range, off_t max, off_t * seek_pos, off_t * end_pos){

	char *first_value;
	char *second_value;
		
	if(client_range == NULL){
		*seek_pos = (off_t)0;	
		*end_pos = max;	
		
		return -1;
		}
	
	/*skip ``bytes'', etc.  Nothing else is supported in HTTP/1.1.  For HTTP/1.2 support, we'd revamp.*/
	first_value = strchr(client_range, '=');

	/*This little bit supports unsupported HTTP syntax.*/
	if(first_value == NULL)
		first_value = client_range;/*maybe ``20-30'' instead of ``bytes=20-30``*/
	else
		*(first_value++);/*Skip up to the first number*/


	/*If range looks like "bytes=-1024" set the min boundary to 0*/
	if(*first_value == '-')/*Don't want a negative number*/
		*seek_pos = (off_t)0;
	else
		*seek_pos = atooff_t(first_value);	


	

	second_value = strchr(client_range, '-');
	if(second_value == NULL)
		return -1;

	*(second_value++);

	*end_pos = atooff_t(second_value);
	if(*end_pos == 0)
		*end_pos  = max;
		
	return 0;
}



#ifndef __BSDSYSTEM__

/*If you'd like to compile with Todd Miller's strlcpy, the creator of the fucntions.
  NOTE:  Tests on Linux prove Karlan's Implementaion is MUCH faster than Todd's*/
#ifdef __TODDS_STRLCPY__

  #include "strlcpy.c"
  #include "strlcat.c"

#else

size_t strlcpy(char * dst, const char * src, size_t size){
	if(src == NULL || dst == NULL || size == 0)
		return 0;


	size_t copy_pos = 0;

	
	while(copy_pos < size - 1){
		if(src[copy_pos] == 0)
			break;
		dst[copy_pos] = src[copy_pos];
		copy_pos++;
	}
	dst[copy_pos] = 0;
	

	return copy_pos;
}

size_t strlcat(char * dst, const char * src, size_t size){
	size_t dst_len = strlen(dst);


	return strlcpy(dst + dst_len, src, size - dst_len) + dst_len;
}
#endif

#endif
